using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

public enum EffectType
{
    Particle,
    Logical,
}
public class EffectSystem : MonoSingleton<EffectSystem>
{
    [SerializeField]
    private Transform effectTran;
    [SerializeField]
    private List<ParticleEffectDataInfo> particleEffectList = new List<ParticleEffectDataInfo>();
    [SerializeField]
    private List<LogicalEffectDataInfo> logicalEffectList = new List<LogicalEffectDataInfo>();

    Dictionary<string, ParticleEffectDataInfo> particleEffectDataDict = new Dictionary<string, ParticleEffectDataInfo>();
    Dictionary<string, LogicalEffectDataInfo> logicalEffectDataDict = new Dictionary<string, LogicalEffectDataInfo>();

    List<string> effectDataNameList = new List<string>();
    List<string> effectNameList = new List<string>();
    private void Start()
    {
        Init();
    }
    /// <summary>
    /// 初始化
    /// </summary>
    void Init()
    {
        foreach (var item in logicalEffectList)
        {
            item.effectName = item.effectData.effectName;
            if (!logicalEffectDataDict.ContainsKey(item.effectData.name))
            {
                logicalEffectDataDict.Add(item.effectData.name, item);
            }
        }
        foreach (var item in particleEffectList)
        {
            item.effectName = item.particleGO.name;
            if (!particleEffectDataDict.ContainsKey(item.effectID))
            {
                particleEffectDataDict.Add(item.effectID, item);
            }
        }
    }
    #region 粒子特效
    public ParticleEffectData GetParticleEffectData(string effectID, Vector3 pos, Vector3 rot, Vector3 scale, bool isAttachGO, bool isWorldSpace)
    {
        ParticleEffectData data = new ParticleEffectData();
        data.ID = effectID;
        data.pos = pos;
        data.rot = rot;
        data.scale = scale;
        data.isAttachGO = isAttachGO;
        data.isWorldSpace = isWorldSpace;
        return data;
    }
    public GameObject GetParticleEffectByID(string effectID, Vector3 pos, Vector3 rot, Vector3 scale, Transform tran = null, bool instantiateInWroldSpace = false)
    {
        GameObject o = null;
        if (particleEffectDataDict.ContainsKey(effectID))
        {
            o = Instantiate(particleEffectDataDict[effectID].particleGO, tran ?? effectTran);
            if (instantiateInWroldSpace)
            {
                o.transform.position = pos;
                o.transform.rotation = Quaternion.Euler(rot);
                o.transform.localScale = scale;
            }
            else
            {
                o.transform.localPosition = pos;
                o.transform.localRotation = Quaternion.Euler(rot);
                o.transform.localScale = scale;
            }
        }
        return o;
    }
    public void AddParticleEffectDataToGO(GameObject originalGO, GameObject go, List<ParticleEffectData> dataList)
    {
        SpawnParticleEffectData data = Instantiate(logicalEffectDataDict["SpawnParticleEffectData"].effectData) as SpawnParticleEffectData;
        data.particleEffectIDList.Clear();
        data.particleEffectIDList = new List<ParticleEffectData>(dataList);
        AddEffectDataToGOByName(originalGO, go, "SpawnParticleEffectData", data);
    }
    #endregion
    #region 逻辑特效
    public LogicalEffectDataBase GetEffectDataByName(string effectDataName, out Action<GameObject, GameObject> onDataChangeFinish)
    {
        onDataChangeFinish = null;
        if (logicalEffectDataDict.ContainsKey(effectDataName))
        {
            LogicalEffectDataBase data = Instantiate(logicalEffectDataDict[effectDataName].effectData);
            onDataChangeFinish = (originalGO, go) =>
            {
                AddEffectDataToGOByName(originalGO, go, effectDataName, data);
            };
            return data;
        }
        return null;
    }
    public void AddEffectToGOByName(GameObject originalGO, GameObject go, string effectDataName)
    {
        if (logicalEffectDataDict.ContainsKey(effectDataName))
        {
            LogicalEffectDataInfo effectInfo = logicalEffectDataDict[effectDataName];
            if (go.GetComponent<LogicalEffectManager>() == null)
            {
                go.AddComponent<LogicalEffectManager>();
            }
            LogicalEffectBase effect = go.AddComponent(Type.GetType(effectInfo.effectName)) as LogicalEffectBase;
            effect.SetData(Instantiate(logicalEffectDataDict[effectDataName].effectData));
            effect.Init(originalGO);
            go.GetComponent<LogicalEffectManager>().OnAddEffect(effect);
        }
    }
    public void AddEffectsTOGOByNames(GameObject originalGO, GameObject go, int effectDataNameIndex)
    {
        foreach (var item in GetEffectDataNamesByIndex(effectDataNameIndex))
        {
            AddEffectToGOByName(originalGO, go, item);
        }
    }
    public void AddEffectDataToGOByName(GameObject originalGO, GameObject go, string effectDataName, LogicalEffectDataBase data)
    {
        if (logicalEffectDataDict.ContainsKey(effectDataName))
        {
            LogicalEffectDataInfo effectInfo = logicalEffectDataDict[effectDataName];
            if (go.GetComponent<LogicalEffectManager>() == null)
            {
                go.AddComponent<LogicalEffectManager>();
            }
            LogicalEffectBase effect = go.AddComponent(Type.GetType(effectInfo.effectName)) as LogicalEffectBase;
            effect.SetData(data);
            effect.Init(originalGO);
            go.GetComponent<LogicalEffectManager>().OnAddEffect(effect);
        }
    }
    //TODO:支持EffectId添加Effect
    #endregion

    public string[] GetEffectDataNameArr()
    {
        effectDataNameList.Clear();
        effectDataNameList.Add("");
        foreach (var item in logicalEffectList)
        {
            if (item.effectData && !effectDataNameList.Contains(item.effectData.name))
            {
                effectDataNameList.Add(item.effectData.name);
            }
        }
        return effectDataNameList.ToArray();
    }
    public string[] GetEffectNameArr()
    {
        effectNameList.Clear();
        effectNameList.Add("");
        foreach (var item in logicalEffectList)
        {
            if (item.effectData && !effectNameList.Contains(item.effectData.effectName))
            {
                effectNameList.Add(item.effectData.effectName);
            }
        }
        return effectNameList.ToArray();
    }
    public List<string> GetEffectNamesByIndex(int indexes)
    {
        List<string> names = new List<string>();
        string[] effectNameArr = GetEffectNameArr();
        if (indexes == -1)
        {
            names = effectNameArr.ToList();
            names.RemoveAt(0);
        }
        else
        {
            string indexStr = Convert.ToString(indexes, 2);
            for (int i = indexStr.Length - 2; i >= 0; i--)
            {
                if (indexStr[i] == '0') continue;
                names.Add(effectNameArr[effectNameArr.Length - 1 - i]);
            }
        }
        return names;
    }
    public List<string> GetEffectDataNamesByIndex(int indexes)
    {
        List<string> names = new List<string>();
        string[] effectDataNameArr = GetEffectDataNameArr();
        if (indexes == -1)
        {
            names = effectDataNameArr.ToList();
            names.RemoveAt(0);
        }
        else
        {
            string indexStr = Convert.ToString(indexes, 2);
            for (int i = indexStr.Length - 2; i >= 0; i--)
            {
                if (indexStr[i] == '0') continue;
                names.Add(effectDataNameArr[effectDataNameArr.Length - 1 - i]);
            }
        }
        return names;
    }
}
[Serializable]
public class ParticleEffectDataInfo
{
    public string effectID;
    [ReadOnly]
    public string effectName;
    public LogicalEffectDataBase effectData;
    public GameObject particleGO;
}
[Serializable]
public class LogicalEffectDataInfo
{
    public string effectID;
    [ReadOnly]
    public string effectName;
    public LogicalEffectDataBase effectData;
}
